🎖️GitЯра🎖️
.github/workflows/post-release-cleanup.yml ca046eddf2b741fb113fc6bf4503f81e06932121 (ca046edd) Text, 7.36 KB
Tff7b72nameTb4b4b4: Ta5d6ffPost-ReleaseTa5d6ff Ta5d6ffCleanup
Tff7b72onTb4b4b4:
Tff7b72workflow_dispatchTb4b4b4:
Tff7b72inputsTb4b4b4:
Tff7b72base_versionTb4b4b4:
Tff7b72descriptionTb4b4b4: Ta5d6ff'Ta5d6ffTheTe6edf3 Ta5d6ffbaseTe6edf3 Ta5d6ffversionTe6edf3 Ta5d6fftoTe6edf3 Ta5d6ffcleanTe6edf3 Ta5d6ffupTe6edf3 Ta5d6ff(e.g.,Te6edf3 Ta5d6ff2.3.0)Ta5d6ff'
Tff7b72requiredTb4b4b4: Ta5d6fftrue
Tff7b72typeTb4b4b4: Ta5d6ffstring
Tff7b72confirm_deletionTb4b4b4:
Tff7b72descriptionTb4b4b4: Ta5d6ff'Ta5d6ffWARNING:Te6edf3 Ta5d6ffThisTe6edf3 Ta5d6ffisTe6edf3 Ta5d6ffaTe6edf3 Ta5d6ffdestructiveTe6edf3 Ta5d6ffaction.Te6edf3 Ta5d6ffSetTe6edf3 Ta5d6fftoTe6edf3 Ta5d6fftrueTe6edf3 Ta5d6fftoTe6edf3 Ta5d6ffperformTe6edf3 Ta5d6ffdeletion.Te6edf3 Ta5d6ffDefaultsTe6edf3 Ta5d6fftoTe6edf3 Ta5d6ffaTe6edf3 Ta5d6ffdryTe6edf3 Ta5d6ffrun.Ta5d6ff'
Tff7b72requiredTb4b4b4: Ta5d6fftrue
Tff7b72typeTb4b4b4: Ta5d6ffboolean
Tff7b72defaultTb4b4b4: Ta5d6fffalse
Tff7b72permissionsTb4b4b4:
Tff7b72contentsTb4b4b4: Ta5d6ffwrite
T8b949e# Destructive (deletes releases + tags): serialize dispatches so two cleanups
T8b949e# can never interleave.
Tff7b72concurrencyTb4b4b4:
Tff7b72groupTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffgithub.workflowTa5d6ff Ta5d6ff}}
Tff7b72cancel-in-progressTb4b4b4: Ta5d6fffalse
Tff7b72jobsTb4b4b4:
Tff7b72cleanup_prereleasesTb4b4b4:
Tff7b72runs-onTb4b4b4: Ta5d6ffubuntu-24.04-arm
Tff7b72timeout-minutesTb4b4b4: Ta5d6ff15
T8b949e# Dispatch inputs reach the shell as environment variables rather than being
T8b949e# interpolated into the script text: base_version is free-form and feeds a
T8b949e# regex that drives `rm -rf` and tag deletion, so a value containing quotes,
T8b949e# $(...) or a newline must not be able to break out of the assignment.
Tff7b72envTb4b4b4:
Tff7b72BASE_VERSIONTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffgithub.event.inputs.base_versionTa5d6ff Ta5d6ff}}
Tff7b72CONFIRM_DELETIONTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffgithub.event.inputs.confirm_deletionTa5d6ff Ta5d6ff}}
Tff7b72stepsTb4b4b4:
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffCheckoutTa5d6ff Ta5d6ffcode
Tff7b72usesTb4b4b4: Ta5d6ffactions/checkout@v7.0.1
Tff7b72withTb4b4b4:
Tff7b72fetch-depthTb4b4b4: Ta5d6ff0
T8b949e# Shared by every step below: reject anything that is not a bare X.Y.Z
T8b949e# before it reaches a regex, a tag deletion or an rm -rf.
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffValidateTa5d6ff Ta5d6ffbase_version
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72set -euo pipefail
Tff7b72if [[ ! "$BASE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
Tff7b72echo "base_version must be a bare X.Y.Z version (got '$BASE_VERSION')." >&2
Tff7b72exit 1
Tff7b72fi
Tff7b72echo "Cleaning up pre-releases for $BASE_VERSION."
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffCleanupTa5d6ff Ta5d6ffpre-releasesTa5d6ff Ta5d6ffandTa5d6ff Ta5d6fftheirTa5d6ff Ta5d6fftags
Tff7b72idTb4b4b4: Ta5d6ffcleanup_releases
Tff7b72envTb4b4b4:
Tff7b72GH_TOKENTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffsecrets.GITHUB_TOKENTa5d6ff Ta5d6ff}}
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72TAG_PREFIX="v${BASE_VERSION}-"
Tff7b72echo "Searching for pre-releases with tag prefix '$TAG_PREFIX'."
Tff7b72RELEASES_TO_DELETE=$(gh release list --json tagName,isPrerelease --limit 100 | jq -r --arg prefix "$TAG_PREFIX" '.[] | select(.isPrerelease == true and .tagName != null and (.tagName | startswith($prefix))) | .tagName')
Tff7b72if [ -z "$RELEASES_TO_DELETE" ]; then
Tff7b72echo "No pre-releases found for base version $BASE_VERSION."
Tff7b72else
Tff7b72if [[ "$CONFIRM_DELETION" == "true" ]]; then
Tff7b72echo "!!! DELETING RELEASES AND TAGS !!!"
Tff7b72echo "The following pre-releases and their tags will be deleted:"
Tff7b72echo "$RELEASES_TO_DELETE"
Tff7b72echo "$RELEASES_TO_DELETE" | xargs -n 1 gh release delete --cleanup-tag --yes
Tff7b72else
Tff7b72echo "DRY RUN: The following pre-releases and their tags would be deleted:"
Tff7b72echo "$RELEASES_TO_DELETE"
Tff7b72fi
Tff7b72fi
T8b949e# The docs site keeps a per-tag snapshot for every open/closed testing tag
T8b949e# in a version cycle (see docs-release.yml). Once vX.Y.Z ships, /vX.Y.Z/
T8b949e# supersedes them all, so reap them to stop gh-pages growing without bound.
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffCleanupTa5d6ff Ta5d6ffpre-releaseTa5d6ff Ta5d6ffdocsTa5d6ff Ta5d6ffsnapshotsTa5d6ff Ta5d6ffonTa5d6ff Ta5d6ffgh-pages
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72set -euo pipefail
Tff7b72DRY_RUN=true
Tff7b72[[ "$CONFIRM_DELETION" == "true" ]] && DRY_RUN=false
Tff7b72if ! git ls-remote --exit-code --heads origin gh-pages >/dev/null 2>&1; then
Tff7b72echo "No gh-pages branch; nothing to clean."
Tff7b72exit 0
Tff7b72fi
Tff7b72work="$(mktemp -d)"
Tff7b72rmdir "$work"
Tff7b72git fetch --quiet origin gh-pages
Tff7b72git worktree add --quiet -B gh-pages "$work" FETCH_HEAD
Tff7b72trap 'git worktree remove --force "$work" 2>/dev/null || true' EXIT
Tff7b72# Reaping is only sound because /vX.Y.Z/ supersedes these snapshots.
Tff7b72# If it is missing, the production docs never published (or this was
Tff7b72# dispatched for the wrong version) and deleting the snapshots would
Tff7b72# destroy the only docs for this version — and whatever the site root
Tff7b72# currently falls back to. Fail closed instead.
Tff7b72if [ ! -d "$work/v${BASE_VERSION}" ]; then
Tff7b72echo "Refusing to reap docs snapshots: /v${BASE_VERSION}/ is not published on gh-pages." >&2
Tff7b72echo "Run Docs Release against the v${BASE_VERSION} tag first." >&2
Tff7b72exit 1
Tff7b72fi
Tff7b72# Dots are wildcards in an ERE, so escape them: an unescaped
Tff7b72# v1.2.3-open.1 pattern would also match a v1x2y3-open.1 directory.
Tff7b72version_re="${BASE_VERSION//./\\.}"
Tff7b72mapfile -t stale < <(
Tff7b72find "$work" -maxdepth 1 -mindepth 1 -type d \
Tff7b72-regextype posix-extended \
Tff7b72-regex ".*/v${version_re}-(open|closed)\.[0-9]+" -printf '%f\n' | sort
Tff7b72)
Tff7b72if [ ${#stale[@]} -eq 0 ]; then
Tff7b72echo "No pre-release docs snapshots found for $BASE_VERSION."
Tff7b72exit 0
Tff7b72fi
Tff7b72printf 'Pre-release docs snapshots for %s:\n' "$BASE_VERSION"
Tff7b72printf ' %s\n' "${stale[@]}"
Tff7b72if [ "$DRY_RUN" = true ]; then
Tff7b72echo "DRY RUN: the directories above would be removed from gh-pages."
Tff7b72exit 0
Tff7b72fi
Tff7b72for d in "${stale[@]}"; do
Tff7b72rm -rf "$work/$d"
Tff7b72done
Tff7b72# Rebuild versions.json (and the root placeholder) from what remains,
Tff7b72# using the same generator the publisher runs.
Tff7b72python3 scripts/docs/regenerate-versions.py "$work"
Tff7b72cd "$work"
Tff7b72git add -A
Tff7b72if git diff --cached --quiet; then
Tff7b72echo "gh-pages already clean."
Tff7b72exit 0
Tff7b72fi
Tff7b72git -c user.name='github-actions[bot]' \
Tff7b72-c user.email='41898282+github-actions[bot]@users.noreply.github.com' \
Tff7b72commit -q -m "docs: reap pre-release snapshots for ${BASE_VERSION}"
Tff7b72git push --quiet origin HEAD:gh-pages
Tff7b72echo "Removed ${#stale[@]} pre-release docs snapshot(s) from gh-pages."
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffCleanupTa5d6ff Ta5d6ffdanglingTa5d6ff Ta5d6ffpre-releaseTa5d6ff Ta5d6fftags
Tff7b72envTb4b4b4:
Tff7b72GITHUB_TOKENTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffsecrets.GITHUB_TOKENTa5d6ff Ta5d6ff}}
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72TAG_PREFIX="v${BASE_VERSION}-"
Tff7b72echo "Searching for any remaining remote pre-release tags with prefix '$TAG_PREFIX'."
Tff7b72# This finds all remote tags matching the pattern. Some may have been deleted in the previous step.
Tff7b72TAGS_TO_DELETE=$(git ls-remote --tags origin "refs/tags/${TAG_PREFIX}*" | awk '{print $2}' | sed 's|refs/tags/||')
Tff7b72if [ -z "$TAGS_TO_DELETE" ]; then
Tff7b72echo "No dangling pre-release tags found."
Tff7b72else
Tff7b72if [[ "$CONFIRM_DELETION" == "true" ]]; then
Tff7b72echo "!!! DELETING DANGLING TAGS !!!"
Tff7b72echo "The following pre-release tags will be deleted:"
Tff7b72# We pipe to xargs which will run the command for each tag.
Tff7b72# If a tag was already deleted by the previous 'release delete' step, this will fail for that tag.
Tff7b72# We add '|| true' to ignore any errors and ensure the workflow doesn't fail.
Tff7b72echo "$TAGS_TO_DELETE" | xargs -n 1 -I {} sh -c 'git push --delete origin {} || true'
Tff7b72else
Tff7b72echo "DRY RUN: The following dangling pre-release tags would be deleted:"
Tff7b72echo "$TAGS_TO_DELETE"
Tff7b72fi
Tff7b72fi
Served by rngit 1.5.2 - Generated in 0.14s